In software development it is important to guarantee the integrity of shared resources. In a multi-thread/process system integrity of shared resources is generally maintained by using variables such as flags and/or semaphores to control resource accesses (read/write) by different processes. The processes typically fall into two groups: 1) Polling or Idle processes and 2) Interrupt processes. The polling or idle processes update the system periodically and are usually scheduled by a round robin algorithm. The interrupt processes handle interrupt requests generated externally (e.g., the user) or internally (e.g., by the system when detecting some type of fault or failure). The variables effectively disable the services to the interrupt requests so that simultaneous accesses (especially writes) to the shared resources by different processes or threads are prohibited.
Processes may be associated with different priorities, so higher priority mission-critical tasks are serviced before lower priority tasks (via a context switch). Under this condition, the global/local variables of an unfinished (lower priority) process will be pushed on the stack, and those of a new (higher priority) process will be fetched and pushed on top of those of the old (lower priority) process. Only after the higher priority process finishes execution and returns control to the old process, may the old process resume its execution by another context switch. The higher priority process is called the interrupt service routine (ISR) since generally higher priority processes take over the control as interrupts. The typical result is that under conditions that interrupts are not desired when shared resource access is in progress, the interrupts are normally ignored (masked) until the shared (critical) information access has been finished.
In some single thread systems, the system or externally generated interrupts should not be masked due to the fact that some of the interrupt requests are one-shot activities (e.g., intermittent failure log). If any of the requests are ignored, the same interrupt requests may not be generated any more, therefore these requests will be lost forever, and the system may behave improperly. In single thread/process systems with limited memory space, where no interrupts may be ignored, it has been impossible to guarantee the integrity of these shared resources when being accessed by normal priority routines and interrupt routines. This is illustrated by two examples.
Case A (modification to different bits) with Xi, Yi, Zi=0,1. The polling process (normal or lower priority process) and interrupt process (higher priority process) each modify a different bit within the shared resource. The interrupt process executes its write operation after the polling process executes its read operation but before the polling process executes its write operation.
Shared Resource: VAR;Bit-wise variable names: VAR0, VAR1, VAR2, VAR3, VAR4, VAR5,VAR6, VAR7 for corresponding bits;Variable memory address: ADDR_SR;Byte information: value X0, X1, X2, X3, X4, X5, X6, X7 for bitsVAR0 to VAR7.Polling (idle) process: read VAR into register R1 from ADDR_SR,modify bit-4 from X4 to Y4, so the register R1 has the informationX0X1X2X3Y4X5X6X7;Interrupt process: (before the above polling process commits the writeoperation), uses register R2 to hold the value of VAR, set the VAR3value to Z3. Write the value Z3 in R2 to memory address ADDR_SR.Now the value at ADDR_SR is possibly X0X1X2Z3X4X5X6X7 due tothe fact that the smallest addressable unit of a write is eight bits (one byte).Polling process: write the value in R1 back into memory addressADDR_SR, so that the final value becomes X0X1X2X3Y4X5X6X7,whereas the expected value should be X0X1X2Z3Y4X5X6X7.
Case B (modification to same control bit) with Xi, Yi, Zi=0,1. The polling process and interrupt process each modify the same bit within the shared resource. The interrupt process executes its write operation after the polling process read operation but before the polling process executes its write operation.
Shared resource: VAR;Bit-wise variable names: VAR0, VAR1, VAR2, VAR3, VAR4, VAR5,VAR6, VAR7 for corresponding bits;Variable memory address: ADDR_SR;Byte information: value X101X2X3X4X5X6X7 for bits VAR0 to VAR7.Polling process: read VAR into register R1 from ADDR_SR,flip bit-4 from X4 to (~X4), so the register R1 has theinformation X0X1X2X3(~X4)X5X6X7,where Xi and ~Xi has the following relationship:Xi = 0   ~Xi = 1Xi = 1   ~Xi = 0Interrupt process: use register R2 to hold the value of VAR, set theVAR4 value to Z4 (Z4 may be equal to X4 or ~X4). Write the valueZ4 in R2 to memory address ADDR_SR. Now the valueat ADDR_SR is possibly X0X1X2X3Z4X5X6X7 due to the fact thatthe smallest addressable unit of a write is eight bits (one byte).Polling process: write the value in R1 back into memory addressADDR_SR, so that the final value becomes X0X1X2X3(~X4)X5X6X7whereas the expected value should be X0X1X2X3Z4X5X6X7. If Z4equals ~X4, then X0X1X2X3(~X4)X5X6X7 and X0X1X2X3Z4X5X6X7are equal, however, since Z4 can be either X4 or ~X4, there is a fiftypercent chance that the wrong result is achieved.
In systems with large amounts of memory and central processing unit (CPU) power, typically multi-thread systems (discussed previously), the common practice is to disable services for interrupt requests so that simultaneous accesses to the shared information (either the same bit or different bit in the same control byte) is prohibited. That is, while modification of the shared resource by the polling task is in progress, interrupts will be ignored until the access privilege is released by the polling task, which does so once it finishes its operation on the shared resource. This ensures the integrity of the shared resource, but is only functional if interrupts are disabled very briefly, since any interrupt blockage introduces the possibility of losing a time-sensitive notification. Such an assumption is safe in larger, multi-threaded systems with more memory and CPU power.
In the two above cases involving a single thread non-mission-critical system, if the interrupt process attempts to modify the same bit, or any other bit(s) in the same byte (as the smallest addressable unit) of the shared information, incorrect results will be obtained. Multi-bit or multi-byte writes may cause even more serious problems. The need to modify bits within an individual byte is typical of systems with limited memory space. Therefore, in single thread non-mission-critical systems with limited memory space, a method of handling all interrupt requests while maintaining the integrity of the shared resources has not been achieved.
Therefore, it would be desirable to provide a system and method for servicing all write requests received via interrupts in single thread non-mission-critical systems with limited memory space and avoiding shared resource conflicts.